<template>
	<view :class="$style.container">
		<!-- 群成员按钮 -->

		<!--内容-->
		<view @touchstart="togglePanel" class="UpView flex-1" :style="{ maxHeight: scrollHeight }">
			<scroll-view scroll-y :scroll-into-view="scrollViewId"
				style="height: 100%;transition: all .2s;box-sizing: border-box;" :style="{ maxHeight: scrollHeight }"
				@scrolltolower="handleMessageListLoading">
				<view v-for="(item, index) in chatList" :key="index">
					<!-- 聊天内容展示 -->
					<chat-content :chatData="item"></chat-content>
				</view>
				<view id="bottom"></view>
			</scroll-view>
		</view>


		<!--输入-->
		<view class="DownView" @tap.prevent.stop="">
			<!--作战反馈-->
			<!-- <image src="@/static/images/chat/feedback.png" class="icon" @click="openFeedbackPage('feedback')"></image> -->

			<!-- 语音输入 -->
			<!-- <image src="@/static/images/chat/voice.png" class="icon" /> -->

			<!--文本输入-->
			<input :cursor-spacing="8" v-model="content" @focus="inputFocus" :adjust-position="false" type="text"
				class="input" placeholder="" />

			<!--表情-->
			<!-- <image @touchend.prevent="toggleEmoji" v-show="!sendBtnShow" src="@/static/images/chat/emoji.svg" class="icon">
			</image> -->

			<!-- 群组成员 -->
			<image src="@/static/images/chat/group_member.png" class="icon" @click="openGroupMemberPage('group')" />
			<!--发送消息-->
			<view @touchend.prevent="sendMessage" v-show="sendBtnShow" class="btn">发送</view>
			<!--打开操作面板-->
			<image @touchend.prevent="toggleFile" v-show="!sendBtnShow" src="@/static/images/chat/group.png" class="icon">
			</image>
		</view>

		<!-- emoji -->
		<!-- <view v-show="showEmoji">
			<view class="bottom-panel" style="height: 200px;">
				<view class="box-item" v-for="(item, index) in 8" :key="index">
					<text>😀</text>
				</view>
			</view>
		</view> -->

		<!-- 附件 -->
		<view v-show="showFile">
			<view class="bottom-panel" style="height: 200px;">
				<view class="box-item" v-for="(item, index) in fileList" :key="index" @tap="handleFile(item)">
					<view class="icon">
						<img style="width: 60rpx;height: 60rpx;" :src="item.icon" alt="">
					</view>
					<text class="label">{{ item.label }}</text>
				</view>
			</view>
		</view>

	</view>
</template>
<script setup lang="ts">

/**
 * 会商页面主要功能：
 * 1. 打开会商页面，会创建 IM 即时通信实例对象 并获取 userSig 进行登陆操作
 * 2. 拉取该警情所关联的 群聊消息，并进行 text、image、video 文件的渲染
 * 3. 发送 text、image、video 格式的消息处理：文本正常通过 im 服务发送；图片及视频先通过wx.uploadFile上传到本地服务器上，并将返回结果通过 im 服务发送，并将值渲染到 发送列表中
 * 4. 目前还无法解析文件上传服务返回的结果；未实现发送位置信息、未实现语音发送
 *
 */

import { queryUserSig } from '@/api'
import { useInstantMessage } from '@/store'
import { computed, onMounted, onUnmounted, reactive, ref } from 'vue';
import TIM from 'tim-wx-sdk';

import ChatContent from '@/components/chat-content/index.vue'

import photoImg from '@/static/images/chat/photo.png';
import cameraImg from '@/static/images/chat/camera.png';
import liveImg from '@/static/images/chat/live.png';
import locationImg from '@/static/images/chat/location.png';
import voiceImg from '@/static/images/chat/voice.png';
import { getLocal } from '@/utils';
import { HTTP_UPLOAD_URL } from '@/config';

import { GDMap_Service_Key, imageTypeList, videoTypeList } from '@/static'

/**
 * 获取当前用户信息
 */
let openid = getLocal('openid')
let lqryInfo: any = getLocal('lqryInfo')

/**
 * 上面scroll-view，下面输入框
 * 输入框上移，其实是scroll-view的高度减少
 * 布局用的是flex column scroll-view自动填充 flex-grow: 1
 * scroll-view有个最大高度，最大高度也是有两个值
 * 下面的固定，控制显示与否，最大高度也是两个变化
 */



/** 聊天信息列表 */
interface ContentType {
	address: string,
	latitude: string,
	longitude: string,
}

type MsgTSType = {
	/** 信息是不是本人发送 */
	isMe: boolean,
	/** 用户姓名 */
	userName: string,
	/** 用户头像 */
	userAvatar: string,
	/** 用户手机号 */
	mobileNumber: string,
	/** 信息类型 text image video map */
	msgType: string,
	/** 信息内容 */
	content: string | ContentType,
}

const chatList = ref<Array<MsgTSType>>([

])

/** 下面的操作面板 -- emoji */
// const showEmoji = ref(false)
// const toggleEmoji = () => {
// 	showFile.value = false
// 	showEmoji.value = true
// 	setScrollHeight(200)
// 	setScrollBottom()
// }

/** 下面的操作面板 -- 附件 */
const showFile = ref(false)
const toggleFile = () => {
	// showEmoji.value = false
	showFile.value = true
	setScrollHeight(200)
	setScrollBottom()
}

/** 聊天面板触发事件 */
const togglePanel = () => {
	showFile.value = false
	// showEmoji.value = false
	setScrollHeight(0)
}

const fileList = reactive([
	{
		id: '1',
		icon: photoImg,
		label: '相册'
	},
	{
		id: '2',
		icon: cameraImg,
		label: '拍摄'
	},
	{
		id: '3',
		icon: liveImg,
		label: '直播'
	},
	{
		id: '4',
		icon: locationImg,
		label: '位置'
	},
	{
		id: '5',
		icon: voiceImg,
		label: '语音'
	}
])

/** 监听 input 输入聚焦 */
const inputFocus = (e: any) => {
	debugger
	togglePanel()
	setScrollBottom()

	// 虚拟键位占了软键盘的高度，所以需要减去
	// 屏幕总高度减去可使用窗口高度就是虚拟键位占的高度单位 rpx
	// 将软键盘的高度减去虚拟键位的高度就是软键盘的真实高度
	// 用一个三元处理，以防止为负数
	let _sysInfo = uni.getSystemInfoSync()
	let _heightDiff = _sysInfo.screenHeight - _sysInfo.windowHeight
	let _diff = e.detail.height - _heightDiff / 2
	let keyHeight = _diff > 0 ? _diff : 0

	setScrollHeight(keyHeight)
	uni.onKeyboardHeightChange(res => {
		let _sysInfo = uni.getSystemInfoSync()
		let _heightDiff = _sysInfo.screenHeight - _sysInfo.windowHeight
		let _diff = res.height - _heightDiff / 2
		let keyHeight = _diff > 0 ? _diff : 0

		setScrollHeight(keyHeight)
	})
}

/** 设置 scrollView 的高度 */
const scrollHeight = ref<string>('calc(100vh - 110rpx)')
const setScrollHeight = (descHeight: number = 0) => {
	scrollHeight.value = `calc(100vh - 110rpx - ${descHeight}px)`
}

/** 设置 scrollView 的滚动条到底部 */
const scrollViewId = ref('')
const setScrollBottom = () => {
	scrollViewId.value = ''
	setTimeout(() => {
		scrollViewId.value = 'bottom'
	});
}

// 发送消息
const content = ref('')
const sendBtnShow = computed(() => Boolean(content.value));

const sendMessage = (obj: any) => {
	// 加入信息
	sendMessageByIM(content.value)
	// 发送成功
	content.value = ''
	setScrollBottom()
}

/** 发送附件 */
const handleFile = (item: any) => {
	if (item.label == '相册') {
		sendImage()
	}
	if (item.label == '拍摄') {
		sendVideo()
	}
	if (item.label == '位置') {
		sendLocation()
	}
	if (item.label === '语音') {

	}
}

/** 上传附件到 文件服务中去 */
function uploadToServiceFile(data: any, type: string) {
	data.forEach((item: any) => {
		uni.uploadFile({
			url: HTTP_UPLOAD_URL + '/upload/path',
			filePath: item,
			name: 'multipartFile',
			formData: {
				'path': 'applet/im/'
			},
			success(res: any) {
				// let transformData: any = JSON.parse(res.data)
				let data: any = JSON.parse(res.data);
				console.log('uploadFile JSON.parse 转换后的值', data);
				sendMessageByIM(data.data.fileUrl);
			}
		})
	})
}

const sendImage = () => {
	uni.chooseImage({
		count: 9,
		sourceType: ['camera', 'album'],
		success: function (res: any) {
			const tempFilePaths: any = res.tempFilePaths
			uploadToServiceFile(tempFilePaths, 'image')
		}
	})
}

const sendVideo = () => {
	uni.chooseVideo({
		sourceType: ['camera', 'album'],
		success: function (res: any) {
			const tempFilePaths: any = [res.tempFilePath];
			uploadToServiceFile(tempFilePaths, 'video')
		}
	});
}

/** 发送位置 */
const sendLocation = () => {
	uni.getLocation({
		success: res => {
			let { latitude, longitude } = res
			uni.chooseLocation({
				latitude,
				longitude,
				success: res => {
					console.log('获取到的地址信息', res);
					// TODO 将地址信息JSON转换，通过 im 发送
					let messageData = { ...res, type: 'map' }
					sendMessageByIM(JSON.stringify(messageData))
				}
			})
		}
	})
}

/** 页面挂载则退出登陆 */
onMounted(() => {
	imLogin()
})

/** 处理接收到的消息 */

/*** 创建 IM 即时通信 实例对象 并进行登陆操作 */

let tim: any = null
const chatStore = useInstantMessage()
async function imLogin() {
	tim = TIM.create({ SDKAppID: 1400672021 })

	bindIMEvent(tim)

	let userSig: string = ''
	await queryUserSig({ userid: openid, expire: 7 * 24 * 3600 }).then((res: any) => {

		if (res.result.resultCode === '000000') {
			// 报错 用于 userSig
			userSig = res.data
			chatStore.setUserSig(res.data)
		}
	}).catch((e: any) => {

	})

	let params = {
		userID: openid || '',
		userSig: userSig || '',
	}

	tim.login(params).then((imResponse: any) => {
		// 获取消息列表
		if (imResponse.data.repeatLogin === true) {

		}
	}).catch((imError: any) => {

	})
}

/**
 * 通过 IM 发送消息
 * @param message: string 发送消息内容 
 */

function sendMessageByIM(message: string) {
	let info: any = tim.createTextMessage({
		to: chatStore.getChatGroup,
		conversationType: TIM.TYPES.CONV_GROUP,
		payload: {
			text: message,
		},
		// v2.18.0起支持群消息已读回执功能，如果您发消息需要已读回执，需购买旗舰版套餐，并且创建消息时将 needReadReceipt 设置为 true
		needReadReceipt: false,
	})
	// 发送消息
	tim.sendMessage(info).then(function (imResponse: any) {
		// 发送成功
		// TODO 将消息push 到 chatList 中
		// 根据 发送的消息数据类型进行切分
		console.log('im发送消息成功', imResponse);
		handleSendSuccess(imResponse)
	}).catch(function (imError: any) {
		// 发送失败
		console.log('im发送消息失败', imError);
	})
}

/*** 处理 IM　历史消息列表 */
function handleHistoryMessage(message: any, isLoad: boolean) {
	let historyMessageList: any = []
	message.forEach((item: any) => {
		let handleMessage = handleMessageType(item.payload?.text)
		let msg = {
			isMe: item.from === openid ? true : false,
			userName: item.from === openid ? lqryInfo.lxrXm : '其他用户',
			userAvatar: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fnimg.ws.126.net%2F%3Furl%3Dhttp%253A%252F%252Fdingyue.ws.126.net%252F2022%252F0107%252Ff5934a7cj00r5b6hz0016c000hs00bxc.jpg%26thumbnail%3D690x10000%26quality%3D75%26type%3Djpg&refer=http%3A%2F%2Fnimg.ws.126.net&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1656667420&t=4aba50bb49064285d2530517e033cf76',
			mobileNumber: lqryInfo.lxrLxdh,
			msgType: item.payload?.text ? handleMessage.type : '',
			content: handleMessage?.type === 'map' ? handleMessage.value : item.payload.text
		}
		historyMessageList.push(msg)
	})
	console.log('处理完消息列表', historyMessageList);

	// 将处理后的消息 传入消息列表中，判断是否二次加载，二次加载则将消息push到 chatList 中
	if (isLoad) {
		chatList.value.push(historyMessageList)
	} else {
		chatList.value = historyMessageList
	}
}

/**
 * 处理发送成功的消息
 */
function handleSendSuccess(res: any) {
	console.log('处理发送成功后的返回值', res);
	let item: any = res.data.message

	let handleMessage = handleMessageType(item.payload?.text)
	let msg = {
		isMe: item.from === openid ? true : false,
		userName: item.from === openid ? lqryInfo.lxrXm : '其他用户',
		userAvatar: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fnimg.ws.126.net%2F%3Furl%3Dhttp%253A%252F%252Fdingyue.ws.126.net%252F2022%252F0107%252Ff5934a7cj00r5b6hz0016c000hs00bxc.jpg%26thumbnail%3D690x10000%26quality%3D75%26type%3Djpg&refer=http%3A%2F%2Fnimg.ws.126.net&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1656667420&t=4aba50bb49064285d2530517e033cf76',
		mobileNumber: lqryInfo.lxrLxdh,
		msgType: item.payload?.text ? handleMessage.type : '',
		content: handleMessage.type === 'map' ? handleMessage.value : item.payload.text
	}
	chatList.value.push(msg)
}


/**
 * 处理接收到的消息内容，根据im传递的payload.text内容判断出发送消息的类型： text、image、video
 * @param text
 */
function handleMessageType(text: string) {
	if (text == undefined) return
	let message: any = {
		type: '',
		value: '',
	}

	// 判断text 内容是否包含 'address', 'map'
	if (text.includes('address') && text.includes('map')) {
		message.type = 'map'
		message.value = JSON.parse(text)
	} else {
		let textList = text.split('.')
		if (imageTypeList.includes(textList[textList.length - 1])) {
			/** 默认 返回 图像类型 */
			message.type = 'image'
			message.value = text
		} else if (videoTypeList.includes(textList[textList.length - 1])) {
			/** 默认 返回 视频类型 */
			message.type = 'video'
			message.value = text
		} else {
			/** 文本消息无法用 . 分割，默认 返回 文本类型 */
			message.type = 'text'
			message.value = text
		}
	}


	return message
}



/** 获取当前会话list */
const currentMessageList = ref<any>([])  // 当前拉取的消息列表
const nextReqMessageID = ref<string>('') // 用于续拉，分页续拉时需传入该字段。
const isCompleted = ref<boolean>(false) // 表示是否已经拉完所有消息。isCompleted 为 true 时，nextReqMessageID 为 ""。

/** 第一次拉群群聊会话列表 */
function getMessageList() {
	tim.getMessageList({ conversationID: `GROUP${chatStore.getChatGroup}`, count: 15 }).then((messageResponse: any) => {
		console.log('第一次拉取群聊会话', messageResponse)
		handleHistoryMessage(messageResponse.data.messageList, false)
		currentMessageList.value = messageResponse.data.messageList
		nextReqMessageID.value = messageResponse.data.nextReqMessageID
		isCompleted.value = messageResponse.data.isCompleted
	})
}

/** 下拉获取 接着获取消息列表 */
function handleMessageListLoading() {
	tim.getMessageList({ conversationID: `GROUP${chatStore.getChatGroup}`, nextReqMessageID: nextReqMessageID.value, count: 15 }).then((messageResponse: any) => {
		console.log('下拉获取更多群聊会话', messageResponse)
		if (messageResponse?.data.messageList.length) {
			handleHistoryMessage(messageResponse.data.messageList, true)
			currentMessageList.value = messageResponse.data.messageList
			nextReqMessageID.value = messageResponse.data.nextReqMessageID
			isCompleted.value = messageResponse.data.isCompleted
		}
	})

}

/**
 * 接收到群聊消息
 * 首先判断 群聊消息的发送人，在将消息内容push到 chatList
 */
function handleReceiveGroupMessage(event: any) {
	// 判断消息的发送人
}

/**
 * 绑定 IM　事件
 * @param tim 
 */
function bindIMEvent(tim: any) {
	// 监听事件，例如：
	tim.on(TIM.EVENT.SDK_READY, function (event: any) {
		// 收到离线消息和会话列表同步完毕通知，接入侧可以调用 sendMessage 等需要鉴权的接口
		// event.name - TIM.EVENT.SDK_READY
		// 获取历史消息列表
		getMessageList()

	});
	tim.on(TIM.EVENT.MESSAGE_RECEIVED, function (event: any) {
		// 系统推送的通知消息
		// 收到推送的单聊、群聊、群提示、群系统通知的新消息，可通过遍历 event.data 获取消息列表数据并渲染到页面
		// event.name - TIM.EVENT.MESSAGE_RECEIVED
		// event.data - 存储 Message 对象的数组 - [Message]
	});
	tim.on(TIM.EVENT.MESSAGE_REVOKED, function (event: any) {
		// 收到消息被撤回的通知
		// event.name - TIM.EVENT.MESSAGE_REVOKED
		// event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isRevoked 属性值为 true
	});
	tim.on(TIM.EVENT.MESSAGE_READ_BY_PEER, function (event: any) {
		// SDK 收到对端已读消息的通知，即已读回执。使用前需要将 SDK 版本升级至 v2.7.0 或以上。仅支持单聊会话。
		// event.name - TIM.EVENT.MESSAGE_READ_BY_PEER
		// event.data - event.data - 存储 Message 对象的数组 - [Message] - 每个 Message 对象的 isPeerRead 属性值为 true
	});
	tim.on(TIM.EVENT.CONVERSATION_LIST_UPDATED, function (event: any) {
		// 收到会话列表更新通知，可通过遍历 event.data 获取会话列表数据并渲染到页面
		// event.name - TIM.EVENT.CONVERSATION_LIST_UPDATED
		// event.data - 存储 Conversation 对象的数组 - [Conversation]
	});
	tim.on(TIM.EVENT.GROUP_LIST_UPDATED, function (event: any) {
		// 收到群组列表更新通知，可通过遍历 event.data 获取群组列表数据并渲染到页面
		// event.name - TIM.EVENT.GROUP_LIST_UPDATED
		// event.data - 存储 Group 对象的数组 - [Group]
		// 接收到群聊消息
		console.log('接收到群聊消息', event);

		handleReceiveGroupMessage(event)
	});
	tim.on(TIM.EVENT.PROFILE_UPDATED, function (event: any) {
		// 收到自己或好友的资料变更通知
		// event.name - TIM.EVENT.PROFILE_UPDATED
		// event.data - 存储 Profile 对象的数组 - [Profile]
	});
	tim.on(TIM.EVENT.BLACKLIST_UPDATED, function (event: any) {
		// 收到黑名单列表更新通知
		// event.name - TIM.EVENT.BLACKLIST_UPDATED
		// event.data - 存储 userID 的数组 - [userID]
	});
	tim.on(TIM.EVENT.ERROR, function (event: any) {
		// 收到 SDK 发生错误通知，可以获取错误码和错误信息
		// event.name - TIM.EVENT.ERROR
		// event.data.code - 错误码
		// event.data.message - 错误信息
	});
	tim.on(TIM.EVENT.SDK_NOT_READY, function (event: any) {
		// 收到 SDK 进入 not ready 状态通知，此时 SDK 无法正常工作
		// event.name - TIM.EVENT.SDK_NOT_READY
	});
	tim.on(TIM.EVENT.KICKED_OUT, function (event: any) {
		// 收到被踢下线通知
		// event.name - TIM.EVENT.KICKED_OUT
		// event.data.type - 被踢下线的原因，例如:
		//    - TIM.TYPES.KICKED_OUT_MULT_ACCOUNT 多实例登录被踢
		//    - TIM.TYPES.KICKED_OUT_MULT_DEVICE 多终端登录被踢
		//    - TIM.TYPES.KICKED_OUT_USERSIG_EXPIRED 签名过期被踢 （v2.4.0起支持）。 
	});
}

/**
 * 会商页面 路由跳转：群聊成员页面和反馈页面
 */
function openGroupMemberPage(type: string) {
	if (type === 'group') {
		uni.navigateTo({ url: '/pages/chat-module/group-members/index' })
	}
	// else if (type === 'feedback') {
	// 	uni.navigateTo({ url: '/pages/chat-module/operation-feedback/index' })
	// }
}

onUnmounted(() => {
	// 页面销毁则退出登陆
	tim.logout().then((imResponse: any) => {

	}).catch((imError: any) => {

	})
})

</script>

<style lang="less" module>
.container {
	display: flex;
	flex-direction: column;
	height: 100vh;
}
</style>

<style lang="less" scoped>
// #9BEA6B  #E5E5E5  #717171
.UpView {
	background: #EEE;
}

.DownView {
	height: 110rpx;
	padding: 0 20rpx;
	box-sizing: border-box;
	border-top: 2upx solid #EEE;
	border-bottom: 2upx solid #EEE;
	display: flex;
	flex-direction: row;
	align-items: center;
	justify-content: space-between;
	background: #F7F7F7;

	.input {
		height: 68upx;
		line-height: 68upx;
		padding: 0 20upx;
		font-size: 28upx;
		border-radius: 10upx;
		background-color: #fff;
		width: calc(100% - 120upx - 20upx - 40upx);
	}

	.icon {
		width: 60upx;
		height: 60upx;
	}

	.btn {
		color: #fff;
		width: 90upx;
		height: 52upx;
		font-size: 24upx;
		line-height: 52upx;
		text-align: center;
		border-radius: 10upx;
		background-color: #2BA245;
	}
}

.bottom-panel {
	transition: all .2s;
	width: 100%;
	height: 200px;
	background: #F7F7F7;
	display: flex;
	flex-direction: row;
	flex-wrap: wrap;
	// display: grid;
	// grid-template-columns: repeat(4,25%);
	// grid-template-rows: repeat(2,autofill);
}

// 附件子项
.box-item {
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
	width: 25%;
	font-size: 10px;

	.icon {
		display: flex;
		justify-content: center;
		align-items: center;
		padding: 24rpx;
		background: #ffffff;
		border-radius: 24rpx;
		text-align: center;
		font-size: 48rpx;
		margin-bottom: 5px;
	}

	.label {
		font-size: 24rpx;
		font-weight: 400;
		color: rgba(39, 40, 50, 0.5);
		line-height: 34rpx;
	}
}
</style>
